
import gamestate
import guiutil
import pygame
import randomplayer
import humanplayer
import epistemiclogicplayer
import gamestateviewer
import time
import modelviewer
import model

ST_NEW = 0
ST_START = 1
ST_NEXT = 2

is_revealed = False
nr_players = 3
nr_stones_pp = 2
current_state = ST_NEW
fast_forward = False
pre_time = time.time()
skip = False

model_show_player = -1

model_shown = False

current_model = None

player_list = [None, None, None, None, None]
player_selection_list = [0, 0, 0, 0, 0]
final_player_list = []

def create_game_menu():
    option_list = []
    option_list.append({"name":"show_model", "label":"show model >>>", "clicked":False, "enabled":False, "mouseover":False})
    option_list.append({"name":"start_next_new", "label":"new game", "clicked":False, "enabled":True, "mouseover":False})
    option_list.append({"name":"fast_forward", "label":"", "clicked":False, "enabled":False, "mouseover":False})
    option_list.append({"name":"reveal", "label":"", "clicked":False, "enabled":False, "mouseover":False})
    option_list.append({"name":"nr_stones_pp", "label":"# stones pp: %d" % nr_stones_pp, "clicked":False, "enabled":False, "mouseover":False})
    option_list.append({"name":"players", "label":"players >>>", "clicked":False, "enabled":False, "mouseover":False})
    option_list.append({"name":"", "label":"", "clicked":False, "enabled":False, "mouseover":False})
    option_list.append({"name":"move_stone", "label":"", "clicked":False, "enabled":False, "mouseover":False})
    option_list.append({"name":"move_swap", "label":"", "clicked":False, "enabled":False, "mouseover":False})
    option_list.append({"name":"move_doit", "label":"", "clicked":False, "enabled":False, "mouseover":False})
    return guiutil.Menu((800, 0), (200, 600), option_list)


def create_players_menu():
    option_list = []
    option_list.append({"name":"back", "label":"<<< back", "clicked":False, "enabled":True, "mouseover":False})
    option_list.append({"name":"player_0", "label":"< FREE SLOT >", "clicked":False, "enabled":True, "mouseover":False})
    option_list.append({"name":"player_1", "label":"< FREE SLOT >", "clicked":False, "enabled":True, "mouseover":False})
    option_list.append({"name":"player_2", "label":"< FREE SLOT >", "clicked":False, "enabled":True, "mouseover":False})
    option_list.append({"name":"player_3", "label":"< FREE SLOT >", "clicked":False, "enabled":True, "mouseover":False})
    option_list.append({"name":"player_4", "label":"< FREE SLOT >", "clicked":False, "enabled":True, "mouseover":False})
    return guiutil.Menu((800, 0), (200, 600), option_list)


def create_move_menu():
    option_list = []
    option_list.append({"name":"move_stone", "label":"stone: black", "clicked":False, "enabled":True, "mouseover":False})
    option_list.append({"name":"move_swap", "label":"swap with: none", "clicked":False, "enabled":True, "mouseover":False})
    option_list.append({"name":"move_doit", "label":"Make move!", "clicked":False, "enabled":True, "mouseover":False})
    return guiutil.Menu((800, 0), (200, 600), option_list)


def create_model_menu():
    option_list = []
    option_list.append({"name":"back", "label":"<<< back", "clicked":False, "enabled":True, "mouseover":False})
    option_list.append({"name":"model_show", "label":"show: all", "clicked":False, "enabled":True, "mouseover":False})
    return guiutil.Menu((800, 0), (200, 600), option_list)


def increase_player_selection(player_idx):
    player_selection_list[player_idx] += 1
    if player_selection_list[player_idx] > 3:
        player_selection_list[player_idx] = 0
    if player_selection_list[player_idx] == 0:
        player_list[player_idx] = None
        return "< FREE SLOT >"
    elif player_selection_list[player_idx] == 1:
        player_list[player_idx] = humanplayer.HumanPlayer()
    elif player_selection_list[player_idx] == 2:
        player_list[player_idx] = randomplayer.RandomPlayer()
    elif player_selection_list[player_idx] == 3:
        player_list[player_idx] = epistemiclogicplayer.EpistemicLogicPlayer()
    else:
        raise Exception("BUG!")
    return player_list[player_idx].get_type_name()


def create_game():
    final_player_list = []
    for player in player_list:
        if not player == None:
            final_player_list.append(player)
    return gamestate.GameState(final_player_list, nr_stones_pp)


if __name__ == "__main__":

    #init:
    pygame.init()
    size=[1000,600]
    screen=pygame.display.set_mode(size)
    pygame.display.set_caption("RUG MAS 2011, by Amir and Ron")

    gs = None

    #Loop until the user clicks the close button.
    done=False
    clock = pygame.time.Clock()

    game_menu = create_game_menu()
    players_menu = create_players_menu()
    move_menu = create_move_menu()
    model_menu = create_model_menu()
    menu = game_menu

    gs_surface = pygame.Surface((800, 500))
    gs_surface.fill([255, 255, 255])

    model_surface = None

    move = {}
    move["stone"] = "black"
    move["swap"] = -1

    while done==False:

        # This limits the while loop to a max of 10 times per second.
        # Leave this out and we will use all CPU we can.
        clock.tick(24)

        for event in pygame.event.get(): # User did something
            if event.type == pygame.QUIT: # If user clicked close
                done=True # Flag that we are done so we exit this loop
            if event.type == pygame.MOUSEBUTTONUP:
                menu.event_clicked()

        # Clear the screen and set the screen background
        screen.fill([255, 255, 255])

        menu_surface = menu.draw()
        screen.blit(menu_surface, (800, 0))

        #increase number of stones:
        if menu.is_clicked("nr_stones_pp"):
            nr_stones_pp += 2
            if nr_stones_pp > 10:
                nr_stones_pp = 2
            menu.set_label("nr_stones_pp", "# stones pp: %d" % nr_stones_pp)
            gs = create_game()
            gs_surface = gamestateviewer.draw_gamestate(gs, True)

        #switch between menus:
        if menu.is_clicked("players"):
            menu = players_menu
        if menu.is_clicked("back"):
            menu = game_menu
            model_shown = False

        players_changed = False
        #select players:
        if menu.is_clicked("player_0"):
            menu.set_label("player_0", increase_player_selection(0))
            players_changed = True
        if menu.is_clicked("player_1"):
            menu.set_label("player_1", increase_player_selection(1))
            players_changed = True
        if menu.is_clicked("player_2"):
            menu.set_label("player_2", increase_player_selection(2))
            players_changed = True
        if menu.is_clicked("player_3"):
            menu.set_label("player_3", increase_player_selection(3))
            players_changed = True
        if menu.is_clicked("player_4"):
            menu.set_label("player_4", increase_player_selection(4))
            players_changed = True
        if players_changed:
            gs = create_game()
            gs_surface = gamestateviewer.draw_gamestate(gs, True)
        if not gs == None and len(gs.get_player_list()) > 0:
            menu.set_enabled("start_next_new", True)
        elif not gs == None:
            menu.set_enabled("start_next_new", False)

        #change reveal state:
        if menu.is_clicked("reveal"):
            is_revealed = not is_revealed
            gs_surface = gamestateviewer.draw_gamestate(gs, is_revealed)
            if is_revealed:
                menu.set_label("reveal", "unreveal")
            else:
                menu.set_label("reveal", "reveal")
        #fast forward:
        if menu.is_clicked("fast_forward"):
            if not fast_forward:
                fast_forward = True
                menu.set_label("fast_forward", "skip")
            else:
                skip = True
                menu.set_label("fast_forward", "")
                menu.set_enabled("fast_forward", False)

        #whenever a new game is created:
        if current_state == ST_NEW:
            if menu.is_clicked("start_next_new"):
                #create new game:
                gs = create_game()

                gs_surface = gamestateviewer.draw_gamestate(gs, True)
                menu.set_label("start_next_new", "start game")
                menu.set_enabled("players", True)
                menu.set_enabled("nr_stones_pp", True)
                menu.set_enabled("reveal", True)
                menu.set_label("reveal", "reveal")
                current_state = ST_START
                menu.set_enabled("show_model", False)
        #whenever the game is started:
        if current_state == ST_START:
            if menu.is_clicked("start_next_new"):
                menu.set_enabled("players", False)
                menu.set_enabled("nr_stones_pp", False)
                menu.set_label("start_next_new", "next turn")
                menu.set_label("fast_forward", "fast forward")
                menu.set_enabled("fast_forward", True)
                skip = False

                current_model = model.Model(gs)
                if nr_stones_pp == 2:
                    menu.set_enabled("show_model", True)

                current_state = ST_NEXT

        if current_state == ST_NEXT and gs.is_finished():
            current_state = ST_NEW
            menu.set_label("start_next_new", "new game")
            menu.set_label("fast_forward", "")
            menu.set_enabled("fast_forward", False)
            fast_forward = False
            gs_surface = gamestateviewer.draw_gamestate(gs, True)
        elif not skip and not gs == None and current_state == ST_NEW:
            gs_surface = gamestateviewer.draw_gamestate(gs, True)

        #whenever the next turn is to be started:
        if current_state == ST_NEXT:
            if menu.is_clicked("start_next_new") or (((fast_forward and (time.time() - pre_time) > 1) or skip) and not gs.is_waiting()):
                pre_time = time.time()

                gs.next_turn()

                if gs.is_waiting():
                    menu = move_menu
                    stones = gs.get_stone_list()[gs.get_next_player()]
                    if stones["black"] > 0:
                        move["stone"] = "black"
                    else:
                        move["stone"] = "white"
                    move["swap"] = -1
                    menu.set_label("move_stone", "stone: " + move["stone"])
                    if move["swap"] == -1:
                        menu.set_label("move_swap", "swap: none")
                    else:
                        menu.set_label("move_swap", "swap: player %d" % move["swap"])
                gs_surface = gamestateviewer.draw_gamestate(gs, is_revealed)

        #change stone to put:
        if menu.is_clicked("move_stone"):
            stones = gs.get_stone_list()[gs.get_next_player()]
            if move["stone"] == "black" and stones["white"] > 0:
                move["stone"] = "white"
            elif stones["black"] > 0:
                move["stone"] = "black"
            menu.set_label("move_stone", "stone: " + move["stone"])
        #swap selection:
        if menu.is_clicked("move_swap"):
            move["swap"] += 1
            if move["swap"] == gs.get_next_player():
                move["swap"] += 1
            if move["swap"] >= len(gs.get_player_list()):
                move["swap"] = -1
            if move["swap"] == -1:
                menu.set_label("move_swap", "swap: none")
            else:
                menu.set_label("move_swap", "swap: player %d" % move["swap"])
        #make move:
        if menu.is_clicked("move_doit"):
            gs.finish_move(move)
            gs_surface = gamestateviewer.draw_gamestate(gs, is_revealed)
            menu = game_menu

        if not gs == None and gs.is_waiting():
            lbl = guiutil.draw_label("make your move >>>", 300, 50, False, 0.2, False)
            screen.blit(lbl, (450, 500))

        #show model:
        if menu.is_clicked("show_model"):
            menu = model_menu
            model_shown = True
            show_model_player = -1

            model_surface = modelviewer.draw_model(current_model.get_model_description(), -1)

        if not model_shown:
            screen.blit(gs_surface, (0, 0))
        else:
            screen.blit(model_surface, (0, 0))

        if menu.is_clicked("model_show"):
            model_show_player += 1
            if model_show_player >= len(player_list):
                model_show_player = -1
            if model_show_player == -1:
                menu.set_label("model_show", "show: all")
            else:
                menu.set_label("model_show", "show: player %d" % model_show_player)
            model_surface = modelviewer.draw_model(current_model.get_model_description(), model_show_player)

        #update screen:
        pygame.display.flip()

    pygame.quit()
